package com.estar.integaration.Parser;

import cn.hutool.core.bean.BeanUtil;
import com.estar.integaration.DS.Vertex;
import com.estar.integaration.Parser.Solver.MaterialMoneyGP;
import com.estar.integaration.Parser.Solver.MaterialMoneyParents;
import com.estar.integaration.entity.Material;
import com.estar.integaration.entity.moneyEntity.MaterialComposition;
import com.estar.integaration.entity.moneyEntity.MaterialMoney;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * Author: YJL
 * Date: 2021/12/20 14:24
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MMParser {

  HashMap<String, List<String>> CFHashMap = null;//物料号和多个父物料list对应的HashMap

  List<List<String>> materialRelationShipList = new LinkedList<>();//点关系的List a-->b-->c
  List<Vertex[]> materialIndexList = new LinkedList<>();//每个文件的点的Array [a,b,c] 用123找abc
  HashMap<String,Integer> cMaterialGroupHashMap ;//物料号和生产车间(组别)
  HashMap<String, MaterialMoney> mmCodeMMHashMap;//物料号和物料账期对象的Hash

  List<List<MaterialMoney>> materiaMoneyGroupList = new LinkedList<>();//装list的大List  二组共担，四组共担，一组，二组

  HashMap<String,Integer> one2fourNumber_GroupHashMap = new HashMap<>();

  public MMParser(List<List<String>> materialRelationShipList, List<Vertex[]> materialIndexList, HashMap<String, Integer> cMaterialGroupHashMap, HashMap<String, MaterialMoney> mmCodeMMHashMap) {
    this.materialRelationShipList = materialRelationShipList;
    this.materialIndexList = materialIndexList;
    this.cMaterialGroupHashMap = cMaterialGroupHashMap;
    this.mmCodeMMHashMap = mmCodeMMHashMap;
  }

  /**
   * 找到有库存的物料号,并且按照分出各组
   * @return
   */
  public void getInventoryMaterialList(){
    //解析出1-4位数字
    one2fourNumber_GroupHashMap = new HashMap<>();
    //形成一二组的key的2-5位为key以及组为value的HashMap
    for(Map.Entry<String,Integer> en : cMaterialGroupHashMap.entrySet()){
      //一组或者二组
      if(en.getValue() == 2 || en.getValue() == 3){
        one2fourNumber_GroupHashMap.put(en.getKey().substring(1,5),en.getValue());
      }
    }

    HashMap<String,List<String>> materialParentsMaterialHashMap =  getchildMaterialFinalParentsMaterial(materialRelationShipList);// <a,{b,c}> 所有物料的父子参考关系(参考哈希表)
    //清除内存
    materialRelationShipList = null;
    System.gc();
//    List<List<MaterialMoney>> allList = new ArrayList<>();
//    List<MaterialMoney> groupOne = new ArrayList<>();//一组
//    List<MaterialMoney> groupTwo = new ArrayList<>();//二组
//    List<MaterialMoney> groupTogtherTwo = new ArrayList<>();//一二组共担
//    List<MaterialMoney> groupTogtherFour = new ArrayList<>();//四组共担
//    List<MaterialMoney> others = new ArrayList<>();//不知道怎么处理
    //遍历所有的物料账期对象
    for(String materialCode : mmCodeMMHashMap.keySet()){
      Boolean inList = false;
      MaterialMoney materialMoney = mmCodeMMHashMap.get(materialCode);//找到物料账期对象
      //所有有账期的物料
      if(materialParentsMaterialHashMap.containsKey(materialCode)){//此账期有父
        List<String> parentsMaterial = materialParentsMaterialHashMap.get(materialCode);//获得此账期的最终父
            if(parentsMaterial == null){
              inList = true;
              materialMoney.setGroup("");
              System.out.printf(materialMoney.getBaseMaterialCode()+"[无父]{四组共担}");
//              groupTogtherFour.add(materialMoney);
              continue;
            }
            if(parentsMaterial.size() == 0){
                  //无父
                  if(materialCode.startsWith("A")){
                    inList = true;
                    //二组共担
                     // TODO 这里应该是固定成某组才对 如果是顶层A码肯定是某组
                    System.out.println(materialMoney.getBaseMaterialCode()+"[0父A]{二组共担}");
//                    groupTogtherTwo.add(materialMoney);
                    materialMoney.setGroup("二组共担");
                  }else {//B开头J开头四组
                    inList = true;
                    //四组共担
                    System.out.println(materialMoney.getBaseMaterialCode()+"[0父B]{四组共担}");
//                    groupTogtherFour.add(materialMoney);
                    materialMoney.setGroup("四组共担");
                  }
            }else if(parentsMaterial.size() == 1){//有一个父
                  //2 一组 3 二组
                  Integer group = cMaterialGroupHashMap.get(parentsMaterial.get(0));
                  if(group == null){//有父，但是父无组
                        inList = true;
                        System.out.println(materialMoney.getBaseMaterialCode() + "[1父空组]{四组共担}");
//                        groupTogtherFour.add(materialMoney);
                        materialMoney.setGroup("四组共担");
                        continue;
                  }
                  if(group == 2){
                        inList = true;
                        System.out.println(materialMoney.getBaseMaterialCode() + "[1父一组]{一组}");
                        materialMoney.setGroup("一组");
//                        groupOne.add(materialMoney);
                  }else if(group == 3){
                        inList = true;
                        System.out.println(materialMoney.getBaseMaterialCode() + "[1父二组]{二组}");
//                        groupTwo.add(materialMoney);
                        materialMoney.setGroup("二组");
                  }else {
                        inList = true;
                        //父的组是1或2,是其他情况
                        System.out.println(materialMoney.getBaseMaterialCode() + "[1父其他]{其他}");
//                        others.add(materialMoney);
                        setAnotherSituation(materialMoney);
//                        materialMoney.setGroup("其他组");
                  }
            }else if(parentsMaterial.size() > 1){
                  //多父,存在没有父的
                  Integer group = -1;
                  for(int i = 0 ; i < parentsMaterial.size() ;i++){//遍历所有的父
                    String parentCode = parentsMaterial.get(i);
                    group = cMaterialGroupHashMap.getOrDefault(parentCode,-1);
                    if(group == 2 || group == 3){
                      break;//找到一个组之后直接break,实在没有就按1或者2或者-1来算
                    }
                  }
                  if(group == 2){
                    inList = true;
                    System.out.println(materialMoney.getBaseMaterialCode() + "[多父组一]{一组}");
//                    groupOne.add(materialMoney);
                    materialMoney.setGroup("一组");
                  }else if(group == 3){
                    inList = true;
                    System.out.println(materialMoney.getBaseMaterialCode() + "[多父组二]{二组}");
//                    groupTwo.add(materialMoney);
                    materialMoney.setGroup("二组");
                  }else {
                    inList = true;
                    System.out.println(materialMoney.getBaseMaterialCode() + "[多父不知道]{四组共担}");
//                    groupTogtherFour.add(materialMoney);
                    materialMoney.setGroup("四组共担");
                  }
        }
      }else {//此账期无父,四组共担
        inList = true;
        System.out.println(materialMoney.getBaseMaterialCode() + "[彻底无父]");
//        others.add(materialMoney);
        setAnotherSituation(materialMoney);
//        materialMoney.setGroup("其他组");
      }
      if(inList == false){
        System.out.println("未入list"+materialMoney.getBaseMaterialCode());
      }
    }

//    allList.add(groupOne);
//    allList.add(groupTwo);
//    allList.add(groupTogtherTwo);
//    allList.add(groupTogtherFour);
//    allList.add(others);
//    return allList;
  }

  /**
   * J编码的2-4位在A的2-4位 则属于此A码的组
   * @param materialMoney
   */
  private void setAnotherSituation(MaterialMoney materialMoney){
     if(materialMoney.getBaseMaterialCode().startsWith("B")){
       materialMoney.setGroup("二组共担");
     }else if(materialMoney.getBaseMaterialCode().startsWith("T")){
       materialMoney.setGroup("二组共担");
       setMoney25Off(materialMoney);
     }else if(materialMoney.getBaseMaterialCode().startsWith("W")){
       materialMoney.setGroup("二组共担");
     }else if(materialMoney.getBaseMaterialCode().startsWith("Y")){
       materialMoney.setGroup("二组共担");
     }else if(materialMoney.getBaseMaterialCode().startsWith("J")){
       if(one2fourNumber_GroupHashMap.containsKey(materialMoney.getBaseMaterialCode().substring(1,5))){
         Integer group = one2fourNumber_GroupHashMap.get(materialMoney.getBaseMaterialCode().substring(1,5));
         if(group == 2){
           materialMoney.setGroup("一组");
         }else if(group == 3){
           materialMoney.setGroup("二组");
         }else {
           materialMoney.setGroup("其他组");
         }
       }else {
         //额外的其他情况
         if(materialMoney.getBaseMaterialCode().startsWith("J03")
             || materialMoney.getBaseMaterialCode().startsWith("J09")
             || materialMoney.getBaseMaterialCode().startsWith("J0735")
             || materialMoney.getBaseMaterialCode().startsWith("J0799")
             || materialMoney.getBaseMaterialCode().startsWith("J0821")
             || materialMoney.getBaseMaterialCode().startsWith("J0703")
         ){
           materialMoney.setGroup("一组");
         } else if(materialMoney.getBaseMaterialCode().startsWith("J0722") || materialMoney.getBaseMaterialCode().startsWith("J0721")){
           materialMoney.setGroup("二组");
         }else {
           materialMoney.setGroup("其他组");
         }
       }
     } else if(materialMoney.getBaseMaterialCode().equals("A8099012")){
       materialMoney.setGroup("一组");
     } else if(materialMoney.getBaseMaterialCode().equals("A0199001")){
       materialMoney.setGroup("一组");
     } else if(materialMoney.getBaseMaterialCode().equals("A0999001")){
       materialMoney.setGroup("一组");
     } else if(materialMoney.getBaseMaterialCode().equals("A0999016")){
       materialMoney.setGroup("一组");
     } else if(materialMoney.getBaseMaterialCode().equals("A0701007")){
       materialMoney.setGroup("一组");
     } else if(materialMoney.getBaseMaterialCode().equals("A0408007")){
       materialMoney.setGroup("一组");
     } else if(materialMoney.getBaseMaterialCode().equals("A8099018")){
       materialMoney.setGroup("一组");
     } else if( materialMoney.getBaseMaterialCode().equals("")
         || materialMoney.getBaseMaterialCode() == null
         || materialMoney.getBaseMaterialCode().equals("null")){
      materialMoney.setGroup("丢弃组");
    } else {
       materialMoney.setGroup("其他组");
     }
  }

  //金额二五折了
  private void setMoney25Off(MaterialMoney materialMoney){
    materialMoney.setAllMoney(materialMoney.getAllMoney() *0.25 );
    materialMoney.setStepOneMoney(materialMoney.getStepOneMoney() * 0.25);
    materialMoney.setStepTwoMoney(materialMoney.getStepTwoMoney() * 0.25);
    materialMoney.setStepThreeMoney(materialMoney.getStepThreeMoney() * 0.25);
    materialMoney.setStepFourMoney(materialMoney.getStepFourMoney() * 0.25);
  }

  /**
   * a--->b--->c
   * a--->d
   * a--->e--->f
   *    //
   *    V
   * <a,{c,d,f}>
   * 找到一个子物料的最终所有父物料 形成Hash
   * @return
   */
  private HashMap<String,List<String>> getchildMaterialFinalParentsMaterial(List<List<String>> materialRelationShipList){
    HashMap<String,List<String>> materialParentsMaterialHashMap = new HashMap<>(); //一个物料对应他的所有的路径的最终结果
    for(List<String> materialRelationShip : materialRelationShipList){//循环所有的List
      if(materialRelationShip.size() > 1){//有父
        String parent = materialRelationShip.get(materialRelationShip.size() - 1);//获得一条路径的最后一个
        String child = materialRelationShip.get(0);//获得子
        if(materialParentsMaterialHashMap.containsKey(child)){//多条路径(一子多父)
          List<String> parentList = materialParentsMaterialHashMap.get(child);
          parentList.add(parent);
          materialParentsMaterialHashMap.put(child,parentList);
        }else {//无父，独子一个
          List<String> parentList = new ArrayList<>();
          parentList.add(parent);
          materialParentsMaterialHashMap.put(child,parentList);
        }
      }else {//无父
        String child = materialRelationShip.get(0);
        materialParentsMaterialHashMap.put(child,new ArrayList<>());
      }
    }
    return materialParentsMaterialHashMap;
  }


  @Deprecated
  public List<List<MaterialMoney>> parse(){
    if(CFHashMap == null || cMaterialGroupHashMap == null || mmCodeMMHashMap == null){
      return null;
    }

    initMaterialMoneyGroupList();
    //处理所有的MaterialMoney
    for(String k : mmCodeMMHashMap.keySet()){
        MaterialMoney materialMoney = mmCodeMMHashMap.get(k);
        materialFindGroup(materialMoney,0);
      }
    return materiaMoneyGroupList;
  }

  @Deprecated
  public List<List<MaterialMoney>> parseLow() throws InvocationTargetException, IllegalAccessException {
    if(CFHashMap == null || cMaterialGroupHashMap == null || mmCodeMMHashMap == null){
      return null;
    }
    initMaterialMoneyGroupList();
    List<MaterialMoneyParents> materialMoneyListhaveParents = new LinkedList<>();//库存账龄物料,有父
    List<MaterialMoney> materialMoneyListnoParents = new LinkedList<>();//库存账龄物料,无父
    //分出有无父的
    for(String k : mmCodeMMHashMap.keySet()){//库存账龄
        if(CFHashMap.containsKey(k)){
          MaterialMoney materialMoney = mmCodeMMHashMap.get(k);
          MaterialMoneyParents materialMoneyParents = new MaterialMoneyParents();
          materialMoneyParents.cloneMaterialMoney(materialMoney);
          materialMoneyParents.setParents(CFHashMap.get(k));
          materialMoneyListhaveParents.add( materialMoneyParents);
        }else {
          materialMoneyListnoParents.add(mmCodeMMHashMap.get(k));
        }
    }
    List<MaterialMoneyGP> materialMoneyGPList = new LinkedList<>();//父有父的(有爷)
    List<MaterialMoneyParents> materialMoneyParentList = new LinkedList<>();//父无父的(无爷)
    //处理有父的,分离出有爷的和没爷的
    for(MaterialMoneyParents materialMoneyParents : materialMoneyListhaveParents){
      List<String> parents = materialMoneyParents.getParents();
      //取出本物料所有的父，寻找父是否有父
      for(String father : parents){
        if(CFHashMap.containsKey(father)){//父仍然有父(有爷)
          //取出爷
          List<String> grandParents = CFHashMap.get(father);
          //给爷赋值
          MaterialMoneyGP materialMoneyGP = new MaterialMoneyGP();
          BeanUtils.copyProperties(materialMoneyParents,materialMoneyGP);
          materialMoneyGP.setGrandParents(grandParents);
          //进List
          materialMoneyGPList.add(materialMoneyGP);
        }else {//父无父(无爷)
          materialMoneyParentList.add(materialMoneyParents);
        }
      }
    }
    return materiaMoneyGroupList;
  }


  private List<List<MaterialMoney>> getIfHaveParentsList(){
    return null;
  }

  private void initMaterialMoneyGroupList(){
    //初始化
    List<MaterialMoney> group0 = new LinkedList<>();//二组共担
    List<MaterialMoney> group1 = new LinkedList<>();//四组共担
    List<MaterialMoney> group2 = new LinkedList<>();//一组
    List<MaterialMoney> group3 = new LinkedList<>();//二组
    List<MaterialMoney> group4 = new LinkedList<>();//不知道怎么处理的
    materiaMoneyGroupList.add(group0);
    materiaMoneyGroupList.add(group1);
    materiaMoneyGroupList.add(group2);
    materiaMoneyGroupList.add(group3);
    materiaMoneyGroupList.add(group4);
  }


  /**
   * 物料找组的方法
   * 分别找到每个物料的所有父物料对应的组,记录index，结果写在res里面
   */
  public Integer materialFindGroup(MaterialMoney materialMoney,int level){
    //拿list
    List<MaterialMoney> group0 = materiaMoneyGroupList.get(0);//二组共担
    List<MaterialMoney> group1 = materiaMoneyGroupList.get(1);//四组共担
    List<MaterialMoney> group2 = materiaMoneyGroupList.get(2);//一组
    List<MaterialMoney> group3 = materiaMoneyGroupList.get(3);//二组
    List<MaterialMoney> group5 = materiaMoneyGroupList.get(4);//不知道啥组
    String thisLevelMaterialCode = materialMoney.getBaseMaterialCode();//拿到本次的子物料编码
    Integer group = cMaterialGroupHashMap.get(materialMoney.getBaseMaterialCode());//瞅瞅自己的组是什么
    List<String> parentMaterialCodeList = CFHashMap.get(thisLevelMaterialCode);//找到本子物料所有的父
    if(group == null){ //大概率是自己无组，但是父有组，进父找    库存物料->生产车间(第一轮，自己无组但有父)
      if(parentMaterialCodeList == null || parentMaterialCodeList.size() == 0) {//无父
        group1.add(materialMoney);
      }else {
        for (String parentCode : parentMaterialCodeList) {
//          materialMoney.getBaseMaterialCode(parentCode);
          materialMoney.setBaseMaterialCode(materialMoney.getBaseMaterialCode() + ":" + level + "----->" + parentCode );
          if(materialFindGroup(materialMoney,level++) != null)
            break;//找到一个组就break
        }
      }
    }else {//自己有组
      if(group == 0 || group == 1){ //电气组与机加工组
        if(parentMaterialCodeList == null || parentMaterialCodeList.size() == 0){//无父
          group1.add(materialMoney);//机加工组和电气没父的二组共担
          return group;
        }else if(parentMaterialCodeList.size() > 0){//有父
          for(String parentCode : parentMaterialCodeList){
//            materialMoney.getBaseMaterialCode(parentCode);
            materialMoney.setBaseMaterialCode(materialMoney.getBaseMaterialCode() + ":" + level + "----->" + parentCode);
            if(materialFindGroup(materialMoney,level++) != null)//找到父了直接break掉出去
              break;
          }
        }
      }else if(group == 2){//一组
//        if(parentMaterialCodeList == null || parentMaterialCodeList.size() > 0){
//          group2.add(materialMoney);
//        }else if(parentMaterialCodeList.size() > 0){//有父
//        }
        group2.add(materialMoney);
        return group;
      }else if(group == 3){//二组
//        if(parentMaterialCodeList == null || parentMaterialCodeList.size() > 0){
//          group3.add(materialMoney);
//        }else if(parentMaterialCodeList.size() > 0){//有父
//          group3.add(materialMoney);
//        }
        group3.add(materialMoney);
        return group;
      }else {
        System.out.println("不知道什么情况的物料:"+materialMoney.getBaseMaterialCode());
      }
    }
    return group;
  }
}
